package com.handu.luna.core.domain.system;

import com.handu.luna.core.domain.BasePersistentDomain;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.jpa.repository.JpaRepository;

import javax.persistence.Entity;
import javax.persistence.PostLoad;
import javax.persistence.PrePersist;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by wangzailiang on 2014/7/15.
 */
@Entity
public class Deliver extends BasePersistentDomain<DeliverRepository>{

    public static final String DELIMITER = ",";



    public enum DeliverType {
        //Online Payment,Cash on Deliver
        OP("在线支付"),COD("货到付款");
        public String description;
        DeliverType(String description) {
            this.description = description;
        }

        public static DeliverType valueOf(int ordinal) {
            if (ordinal < 0 || ordinal >= values().length) {
                throw new IndexOutOfBoundsException("Invalid ordinal");
            }
            return values()[ordinal];
        }
    }

    @NotNull(message = "请输入配送方式名称")
    @Size(max = 100,message = "最大不能超过100个字符")
    private String name;
    @NotNull(message = "请输入配送方式描述")
    @Size(max = 254 , message = "最大不能超过255个字符")
    private String description;
    private String types;
    private String deliverAreas;
    private boolean displayed;

    @Transient private List<Long> deliverAreaIdList;
    @Transient private List<DeliverArea> deliverAreaList;
    @Transient private List<DeliverType> deliverTypeList;

    public List<DeliverArea> filterAreas() {

        List<DeliverArea> deliverAreaListAll = context.getDeliverAreaRepository().findAll();
        if(null != this.getDeliverAreaList()) {
           deliverAreaListAll.removeAll(this.getDeliverAreaList());
        }
        return deliverAreaListAll;
    }

    @PostLoad
    public void init() {
        if (StringUtils.isNotBlank(deliverAreas)) {
            deliverAreaList = new ArrayList<>();
            for (String strId : this.strToList(deliverAreas)) {
                long deliverAreaId = Long.parseLong(strId);
                deliverAreaList.add(context.getDeliverAreaRepository().findOne(deliverAreaId));
            }
        }
        if (StringUtils.isNotBlank(types)) {
            deliverTypeList = new ArrayList<>();
            for (String strId : this.strToList(types)) {
                int deliverAreaId = Integer.parseInt(strId);
                deliverTypeList.add(DeliverType.valueOf(deliverAreaId));
            }
        }
    }

    @PrePersist
    public void prePersist() {
        if(StringUtils.isBlank(deliverAreas)) {
            if (CollectionUtils.isNotEmpty(deliverAreaIdList)) {
                deliverAreas = this.listToStr(deliverAreaIdList);
            }
        }

        if (CollectionUtils.isNotEmpty(deliverTypeList)) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < deliverTypeList.size(); i++) {
                sb.append(deliverTypeList.get(i).ordinal());
                sb.append(DELIMITER);
            }
            types = sb.toString();
        }
    }

    public void update() {
        prePersist();
        context.getDeliverRepository().save(this);
    }

    public String listToStr(List<Long> list) {
        StringBuilder sb = new StringBuilder();
        for (Long id : list) {
            sb.append(String.valueOf(id)).append(DELIMITER);
        }
        return sb.toString();
    }

    public List<String> strToList(String arrayString) {
        List<String> list = new ArrayList<>();
        for (String item : arrayString.split(DELIMITER)) {
            list.add(item);
        }
        return list;
    }

    public Deliver(){}

    public Deliver(String name, String description, String types) {
        this.name = name;
        this.description = description;
        this.types = types;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getTypes() {
        return types;
    }

    public void setTypes(String types) {
        this.types = types;
    }

    public List<DeliverType> getDeliverTypeList() {
        return deliverTypeList;
    }

    public void setDeliverTypeList(List<DeliverType> deliverTypeList) {
        this.deliverTypeList = deliverTypeList;
    }

    public List<DeliverArea> getDeliverAreaList() {
        return deliverAreaList;
    }

    public void setDeliverAreaList(List<DeliverArea> deliverAreaList) {
        this.deliverAreaList = deliverAreaList;
    }

    public String getDeliverAreas() {
        return deliverAreas;
    }

    public void setDeliverAreas(String deliverAreas) {
        this.deliverAreas = deliverAreas;
    }

    public List<Long> getDeliverAreaIdList() {
        return deliverAreaIdList;
    }

    public void setDeliverAreaIdList(List<Long> deliverAreaIdList) {
        this.deliverAreaIdList = deliverAreaIdList;
    }

    public boolean isDisplayed() {
        return displayed;
    }

    public void setDisplayed(boolean displayed) {
        this.displayed = displayed;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
    public void merge(String[] fields) {
        List<DeliverType> typeList = this.getDeliverTypeList();
        if(!this.isNew()){
			Object thisDomainInDB = null;
			try {
                thisDomainInDB = BeanUtils.cloneBean(((JpaRepository) getRepository()).findOne(this.getId()));
			} catch (IllegalAccessException | InstantiationException
					| InvocationTargetException | NoSuchMethodException e1) {
				logger.debug("error in copy merge a domain",e1);
			}
			for(String field : fields){
				try {
                    String property = BeanUtils.getProperty(this,field);
                    if(field.endsWith("Date") || field.endsWith("beginTime") ||  field.endsWith("endTime")) {
                        Date date = new SimpleDateFormat("EE MMM dd HH:mm:ss 'CST' yyyy", java.util.Locale.US).parse(property);
                        BeanUtils.copyProperty(thisDomainInDB, field, date);
                    }else {
                        BeanUtils.copyProperty(thisDomainInDB, field, property);
                    }
				} catch (IllegalAccessException | InvocationTargetException
						| NoSuchMethodException e) {
					logger.debug("error in copy merge a domain",e);
				} catch (ParseException e) {
                    e.printStackTrace();
                }
            }
			try {
				BeanUtils.copyProperties(this, thisDomainInDB);
			} catch (IllegalAccessException | InvocationTargetException e) {
				logger.debug("error in copy merge a domain",e);
			}
            this.setDeliverTypeList(typeList);
		}
    }
}
